﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace BlueLotus7
{
    public class BinaryManager
    {
        #region Fields

        protected string baseVirtualDirectory = null;
        protected string basePhysicalDirectory = null;
        protected string category = string.Empty;

        #endregion

        #region Property

        public string PhysicalPath
        {
            get
            {
                return baseVirtualDirectory;
            }
        }

        public string VirtualPath
        {
            get
            {
                return basePhysicalDirectory;
            }
        }

        #endregion

        #region Constructor

        public BinaryManager(string baseVirtualDirectory, string basePhysicalDirectory)
            : this(baseVirtualDirectory, basePhysicalDirectory, string.Empty)
        {
        }

        protected BinaryManager(string baseVirtualDirectory, string basePhysicalDirectory, string category)
        {
            this.baseVirtualDirectory = baseVirtualDirectory;
            this.basePhysicalDirectory = basePhysicalDirectory;
            this.category = category;

            Initialize();
        }

        #endregion

        protected virtual void Initialize()
        {
            if (string.IsNullOrWhiteSpace(this.baseVirtualDirectory))
            {
                this.baseVirtualDirectory = "BinaryLibrary";
            }

            if (string.IsNullOrWhiteSpace(this.basePhysicalDirectory))
            {
                this.basePhysicalDirectory = System.Web.HttpContext.Current.Server.MapPath(this.baseVirtualDirectory);
            }

            if (!string.IsNullOrWhiteSpace(this.category))
            {
                this.baseVirtualDirectory = Path.Combine(this.baseVirtualDirectory, this.category);
                this.basePhysicalDirectory = Path.Combine(this.basePhysicalDirectory, this.category);
            }

            if (!Directory.Exists(this.basePhysicalDirectory))
            {
                Directory.CreateDirectory(this.basePhysicalDirectory);
            }
        }

        public string GetPhysicalPath(Guid binaryKey, string extension = null)
        {
            return GetPath(this.basePhysicalDirectory, binaryKey, extension).Replace('/', '\\'); ;
        }

        public string GetVirtualPath(Guid binaryKey, string extension = null)
        {
            return GetPath(this.baseVirtualDirectory, binaryKey, extension).Replace('\\', '/'); ;
        }

        protected string GetPath(string basePath, Guid binaryKey, string extension = null)
        {
            return GetPath(basePath, GenerateRelativePath(binaryKey, extension));
        }

        protected string GetPath(string basePath, string relativePath)
        {
            return Path.Combine(basePath, relativePath);
        }

        protected string GenerateIndexPath(Guid binaryKey)
        {
            string guid = binaryKey.ToString();
            string path = guid.Substring(0, 2);
            path = Path.Combine(path, guid.Substring(0, 4));
            path = Path.Combine(path, guid.Substring(0, 6));
            path = Path.Combine(path, guid.Substring(0, 8));

            return path;
        }

        protected string GenerateRelativePath(Guid binaryKey, string extension = null)
        {
            string path = Path.Combine(GenerateIndexPath(binaryKey), binaryKey.ToString());

            if (!string.IsNullOrWhiteSpace(extension))
            {
                path += "." + extension;
            }

            return path;
        }

        public static FileStream GetBinaryStream(string physicalFullPath)
        {
            FileStream result = null;

            if (!string.IsNullOrWhiteSpace(physicalFullPath) && File.Exists(physicalFullPath))
            {
                result = new FileStream(physicalFullPath, FileMode.Open);
            }

            return result;
        }

        public static byte[] GetBinaryBytes(string physicalFullPath)
        {
            FileStream stream = GetBinaryStream(physicalFullPath);
            byte[] bytes = null;

            if (stream != null)
            {

                try
                {
                    bytes = new byte[(int)stream.Length];
                    stream.Read(bytes, 0, bytes.Length);
                }
                catch
                {
                    throw;
                }
                finally
                {
                    stream.Close();
                    stream.Dispose();
                }
            }

            return bytes;
        }
    }

    public class ImageManager : BinaryManager
    {
        protected const string originalImageFolderName = "Original";
        protected const string thumbImageFolderName = "Thumb";

        protected string originalFolder = string.Empty;
        protected string thumbFolder = string.Empty;

        public ImageManager(string baseVirtualDirectory, string basePhysicalDirectory)
            : base(baseVirtualDirectory, basePhysicalDirectory, "Images")
        {
        }

        public string GetPhysicalPath(string subFolder, Guid binaryKey, string extension = null)
        {
            return GetPath(Path.Combine(this.basePhysicalDirectory, subFolder), binaryKey, extension);
        }

        public string GetVirtualPath(string subFolder, Guid binaryKey, string extension = null)
        {
            return GetPath(Path.Combine(this.baseVirtualDirectory, subFolder), binaryKey, extension);
        }

        public string GetOriginalPhysicalPath(Guid binaryKey, string extension = null)
        {
            return GetPath(Path.Combine(this.basePhysicalDirectory, originalImageFolderName), binaryKey, extension);
        }

        public string GetOriginalVirtualPath(Guid binaryKey, string extension = null)
        {
            return GetPath(Path.Combine(this.baseVirtualDirectory, originalImageFolderName), binaryKey, extension);
        }

        public string GetThumbPhysicalPath(Guid binaryKey, string extension = null)
        {
            return GetPath(Path.Combine(this.basePhysicalDirectory, thumbImageFolderName), binaryKey, extension);
        }

        public string GetThumbVirtualPath(Guid binaryKey, string extension = null)
        {
            return GetPath(Path.Combine(this.baseVirtualDirectory, thumbImageFolderName), binaryKey, extension);
        }
    }

}